#include "Scene.h"

void Scene::traceRay(Image& render)
{
	Ray *r;
	Ray rGlobal;
	Matrix repere;
	Matrix changement;
	Vector vEcran;
	Intersection inter = Intersection();
	Intersection bestInter = Intersection();
	Vector v;
	vector<Object *>::iterator id;
	int c;
	Illumination* illum = new Phong();
	Color col, res;
	bool intersection, first;
	
	repere=Matrix::scopeChange(obs->getLocation(), Vector(obs->getLocation(),obs->getDestination()));
	changement=repere.transposed();
	
	for(int i=-w/2;i<w/2;i++)
	{
		for(int j=-h/2;j<h/2;j++)
		{
			res = Color();
			for(float k=(i-0.5);k<(i+1);k=k+PAS_ANTI_ALIASING)
			{
				for(float l=(j-0.5);l<(j+1);l=l+PAS_ANTI_ALIASING)
				{
					first = true;

					vEcran= Vector(obs->getLocation(), Point(k,l,obs->getFocal()));
					vEcran.normalize();

					v=(changement * (vEcran));
					v.normalize();

					rGlobal= Ray(obs->getLocation(), v);
					for(id = objects.begin(); id != objects.end(); id++)
					{	
						intersection = (*id)->intersection(rGlobal, inter);
						
						if(intersection)
						{
							if(!first && inter.getDistance() < bestInter.getDistance())
							{
								bestInter=inter;
								col = illum->illumination(bestInter,(**id), *this, rGlobal, MIROR);
							}
							if(first)
							{
								first = false;
								bestInter=inter;
								col = illum->illumination(bestInter,(**id), *this, rGlobal, MIROR);
							}
						}
					}
					if(first)
					{
						res += background; 
					}
					else
					{	
						res += col;
					}
				}
			}
			res.div(9);
			if(res.getR()>1) res.setR(1);
			if(res.getG()>1) res.setG(1);
			if(res.getB()>1) res.setB(1);

			if(res.getR()<0) res.setR(0);
			if(res.getG()<0) res.setG(0);
			if(res.getB()<0) res.setB(0);
			

			render.setColor(i+w/2,j+h/2,res);
		}
		if (((i+w/2)*10000/w)%1000 == 0) cout << ((i+w/2)*100/w) << "%" << endl;
	}
}


void Scene::traceRayAdaptatif(Image& render)
{
	Ray *r;
	Ray rGlobal;
	Matrix repere;
	Matrix changement;
	Vector vEcran;
	Intersection inter = Intersection();
	Intersection bestInter = Intersection();
	Vector v;
	vector<Object *>::iterator id;
	int c;
	Illumination* illum = new Phong();
	Color col, oldRes, res;
	bool intersection, first, pair=true, premier;
	
	repere=Matrix::scopeChange(obs->getLocation(), Vector(obs->getLocation(),obs->getDestination()));
	changement=repere.transposed();
	
	for(int j=-h/2;j<h/2;j++)
	{ premier = true;
		for(int i=-w/2;i<w/2;i++)
		{
			
			res = Color();

			first = true;
			if(pair)
				vEcran= Vector(obs->getLocation(), Point(i,j,obs->getFocal()));
			else
				vEcran= Vector(obs->getLocation(), Point(i,j+1,obs->getFocal()));
			vEcran.normalize();

			v=(changement * (vEcran));
			v.normalize();

			rGlobal= Ray(obs->getLocation(), v);
			for(id = objects.begin(); id != objects.end(); id++)
			{	
				intersection = (*id)->intersection(rGlobal, inter);

				if(intersection)
				{
					if(!first && inter.getDistance() < bestInter.getDistance())
					{
						bestInter=inter;
						col = illum->illumination(bestInter,(**id), *this, rGlobal, MIROR);
					}
					if(first)
					{
						first = false;
						bestInter=inter;
						col = illum->illumination(bestInter,(**id), *this, rGlobal, MIROR);
					}
				}
			}
			if(first)
			{
				oldRes = res;
				res = background; 
			}
			else
			{	
				oldRes = res;
				res = col;
			}
			if(res.getR()>1) res.setR(1);
			if(res.getG()>1) res.setG(1);
			if(res.getB()>1) res.setB(1);
			
			if(res.getR()<0) res.setR(0);
			if(res.getG()<0) res.setG(0);
			if(res.getB()<0) res.setB(0);

			
			if(!premier)
			{
				 if(pair)
				 {
					render.setColor(i+w/2,j+h/2,PixelColor(i-1, j+1, oldRes, i,j, res, 1, changement));
				 }
				 else
				 {
					render.setColor(i+w/2,j+h/2,PixelColor(i-1, j, oldRes, i,j+1, res, 1, changement));
				 }
			}
			
			pair=(!pair);
			premier = false;
		}
		if (((j+w/2)*10000/w)%1000 == 0) cout << ((j+w/2)*100/w) << "%" << endl;
	}
}

Color Scene::PixelColor(float x1, float y1, Color& color1, float x2, float y2, Color& color2, int iteration, Matrix& changement)
{
	Color col, res;
	if(iteration>= 3) 
	{
		res = color1 + color2;
		res.div(2);
		return (res);
	}
	Ray rGlobal;

	Vector vEcran;
	Intersection inter = Intersection();
	Intersection bestInter = Intersection();
	Vector v;
	vector<Object *>::iterator id;
	
	Phong illum = Phong();
	
	bool intersection, first;

	Color color3, color4, color5;
	if(x1 > x2)
	{

		for(int i=1;i<4;i++)
		{
			first = true;
			switch(i)
			{
				case 1: vEcran= Vector(Point(0,0,0), Point(x1 - ((x1 - x2)/2), y1 + ((y2 - y1)/2)  ,obs->getFocal())); break;
				case 2: vEcran= Vector(Point(0,0,0), Point(x2, y1,obs->getFocal())); break;
				case 3: vEcran= Vector(Point(0,0,0), Point(x1, y2,obs->getFocal())); break;
			}

			vEcran.normalize();

			v=(changement * (vEcran));
			v.normalize();

			rGlobal= Ray(obs->getLocation(), v);
			for(id = objects.begin(); id != objects.end(); id++)
			{	
				intersection = (*id)->intersection(rGlobal, inter);

				if(intersection)
				{
					if(!first && inter.getDistance() < bestInter.getDistance())
					{
						bestInter=inter;
						col = illum.illumination(bestInter,(**id), *this, rGlobal, MIROR);
					}
					if(first)
					{
						first = false;
						bestInter=inter;
						col = illum.illumination(bestInter,(**id), *this, rGlobal, MIROR);
					}
				}
			}
			if(first)
			{
				switch(i)
				{
					case 1:  color3 = background; break;
					case 2:  color4 = background; break;
					case 3:  color5 = background; break;
				}
			}
			else
			{	
				switch(i)
				{
					case 1:  color3 = col; break;
					case 2:  color4 = col; break;
					case 3:  color5 = col; break;
				}
			}
		}
		if( (abs(color1.getR()-color3.getR())+ abs(color1.getB()-color3.getB()) + abs(color1.getG()-color3.getG()))>0,2 )
			color1 = PixelColor(x1, y1, color1, x1 - ((x1 - x2)/2), y1 + ((y2 - y1)/2), color3, iteration+1, changement);
		if( (abs(color2.getR()-color3.getR())+ abs(color2.getB()-color3.getB()) + abs(color2.getG()-color3.getG()))>0,2 )
			color2 = PixelColor(x2, y2, color2, x1 - ((x1 - x2)/2), y1 + ((y2 - y1)/2), color3, iteration+1, changement);
		if( (abs(color4.getR()-color3.getR())+ abs(color4.getB()-color3.getB()) + abs(color5.getG()-color3.getG()))>0,2 )
			color4 = PixelColor(x2, y1, color4, x1 - ((x1 - x2)/2), y1 + ((y2 - y1)/2), color3, iteration+1, changement);
		if( (abs(color5.getR()-color3.getR())+ abs(color5.getB()-color3.getB()) + abs(color5.getG()-color3.getG()))>0,2 )
			color5 = PixelColor(x1, y2, color5, x1 - ((x1 - x2)/2), y1 + ((y2 - y1)/2), color3, iteration+1, changement);
		res = color1 + color2 + color4 + color5;
		res.div(4);
		return (res);
	}
	else
	{
	
		for(int i=1;i<4;i++)
		{
			first = true;
			switch(i)
			{
				case 1: vEcran= Vector(Point(0,0,0), Point(x1 + ((x1 - x2)/2), y1 + ((y2 - y1)/2)  ,obs->getFocal())); break;
				case 2: vEcran= Vector(Point(0,0,0), Point(x2, y1,obs->getFocal())); break;
				case 3: vEcran= Vector(Point(0,0,0), Point(x1, y2,obs->getFocal())); break;
			}

			vEcran.normalize();

			v=(changement * (vEcran));
			v.normalize();

			rGlobal= Ray(obs->getLocation(), v);
			for(id = objects.begin(); id != objects.end(); id++)
			{	
				intersection = (*id)->intersection(rGlobal, inter);

				if(intersection)
				{
					if(!first && inter.getDistance() < bestInter.getDistance())
					{
						bestInter=inter;
						col = illum.illumination(bestInter,(**id), *this, rGlobal, MIROR);
					}
					if(first)
					{
						first = false;
						bestInter=inter;
						col = illum.illumination(bestInter,(**id), *this, rGlobal, MIROR);
					}
				}
			}
			if(first)
			{
				switch(i)
				{
					case 1:  color3 = background; break;
					case 2:  color4 = background; break;
					case 3:  color5 = background; break;
				}
			}
			else
			{	
				switch(i)
				{
					case 1:  color3 = col; break;
					case 2:  color4 = col; break;
					case 3:  color5 = col; break;
				}
			}
		}
		if( (abs(color1.getR()-color3.getR())+ abs(color1.getB()-color3.getB()) + abs(color1.getG()-color3.getG()))>0,2 )
			color1 = PixelColor(x1, y1, color1, x1 - ((x1 - x2)/2), y1 + ((y2 - y1)/2), color3, iteration+1, changement);
		if( (abs(color2.getR()-color3.getR())+ abs(color2.getB()-color3.getB()) + abs(color2.getG()-color3.getG()))>0,2 )
			color2 = PixelColor(x2, y2, color2, x1 - ((x1 - x2)/2), y1 + ((y2 - y1)/2), color3, iteration+1, changement);
		if( (abs(color4.getR()-color3.getR())+ abs(color4.getB()-color3.getB()) + abs(color5.getG()-color3.getG()))>0,2 )
			color4 = PixelColor(x2, y1, color4, x1 - ((x1 - x2)/2), y1 + ((y2 - y1)/2), color3, iteration+1, changement);
		if( (abs(color5.getR()-color3.getR())+ abs(color5.getB()-color3.getB()) + abs(color5.getG()-color3.getG()))>0,2 )
			color5 = PixelColor(x1, y2, color5, x1 - ((x1 - x2)/2), y1 + ((y2 - y1)/2), color3, iteration+1, changement);
		res = color1 + color2 + color4 + color5;
		res.div(4);
		return (res);
	}
	
}
